#include "gtc_client_pal.h"
#include "data.h"
#include "record.h"
#include "rtc.h"
#include "log.h"
#include "utility.h"
#include "charger.h"

#include <assert.h>
#include <string.h>

static const struct ClientCallback g_client_callback={
    gtc_send_touch_charge_idle,
    gtc_send_touch_charge_stoped,
    gtc_send_touch_error_occured,
    gtc_send_touch_error_recovered,
    gtc_send_touch_card_start_charge,
    gtc_charger_state_reup,
};


void pal_set_callback(void){
    dev_set_client_callback(&g_client_callback);
}

void pal_init(void){
    pal_set_callback();
    record_init();
}

struct ClientUserGunInfo *pal_get_user_client_gun_data(void){
    return dev_get_user_client_gun_data();
}
struct  ClientUserBmsInfo *pal_get_user_client_bms_data(void){
    return dev_get_user_client_bms_data();
}

void get_kwh_zone_str(const uint16_t *kwh, char_t *str){
    char_t value[25];
    
    for(int32_t i=0;i<48;i++){
        if (i != 0){
            strcat(str, ",");
        }
        memset(value, 0, sizeof(value));
        if (kwh[i] == 0){
            snprintf(value, sizeof(value), "%d", kwh[i]);
        }else{
            snprintf(value, sizeof(value), "%d.%02d",kwh[i]/100, kwh[i]%100);
        }
        strcat(str, value);
    }
}

int32_t get_kwh_zone_value(const char_t *str, uint16_t *kwh){
    return get_tzone_value(str, kwh, 48);
}

//记录打包
static void gtc_pack_record(const struct GtcBillInfo *bill, char_t *buf){
    set_cmd_str(buf, "devid=", bill->dev_id);
    set_cmd_value(buf, "&gunid=", bill->gun_id);
    set_cmd_str(buf, "&userid=", bill->user_id);
    set_cmd_str(buf, "&orderid=", bill->order_id);
    set_cmd_value(buf, "&ctype=", bill->charge_type);
    set_cmd_float(buf, "&cvalue=", bill->charge_type_value);
    set_cmd_value(buf, "&btime=", bill->charge_start_time);
    set_cmd_value(buf, "&etime=", bill->charge_end_time);
    set_cmd_value(buf, "&ctime=", bill->charge_time);
    set_cmd_value(buf, "&bsoc=", bill->start_soc);
    set_cmd_value(buf, "&esoc=", bill->end_soc);
    set_cmd_str(buf, "&end=", bill->err_no);
    set_cmd_float(buf, "&ckwh=", bill->charge_kwh_amount);
    set_cmd_float(buf, "&bkwh=", bill->start_charge_kwh_meter);
    set_cmd_float(buf, "&ekwh=", bill->end_charge_kwh_meter);
    set_cmd_float(buf, "&ctfee=", bill->total_charge_fee);
    set_cmd_float(buf, "&stfee=", bill->total_service_fee);
    set_cmd_bcd(buf, "&vin=", bill->car_vin, GTC_MAX_CAR_VIN_LEN);
    char_t kwh_zone_str[200]={0};
    get_kwh_zone_str(bill->kwh_amount, kwh_zone_str);
    set_cmd_str(buf, "&tzone=",kwh_zone_str);   
    set_cmd_value(buf, "&cmode=", bill->start_type);
    strcat(buf, "\n");
}

static void gtc_unpack_record(const char_t *buf, struct GtcBillInfo *bill){
    get_cmd_str(buf, "devid", bill->dev_id);
    bill->gun_id = get_cmd_value(buf, "gunid");
    get_cmd_str(buf, "userid", bill->user_id);
    get_cmd_str(buf, "orderid", bill->order_id);
    bill->charge_type = get_cmd_value(buf, "ctype");
    bill->charge_type_value = get_cmd_float(buf, "cvalue");
    bill->charge_start_time = get_cmd_value(buf, "btime");
    bill->charge_end_time = get_cmd_value(buf, "etime");
    bill->charge_time = get_cmd_value(buf, "ctime");
    bill->start_soc = get_cmd_value(buf, "bsoc");
    bill->end_soc = get_cmd_value(buf, "esoc");
    get_cmd_str(buf, "end", bill->err_no);
    bill->charge_kwh_amount = get_cmd_float(buf, "ckwh");
    bill->start_charge_kwh_meter = get_cmd_float(buf, "bkwh");
    bill->end_charge_kwh_meter = get_cmd_float(buf, "ekwh");
    bill->total_charge_fee = get_cmd_float(buf, "ctfee");
    bill->total_service_fee = get_cmd_float(buf, "stfee");
    get_cmd_bcd(buf, "vin", bill->car_vin, GTC_MAX_CAR_VIN_LEN);
    char_t kwh_zone_str[200]={0};
    get_cmd_str(buf, "tzone", kwh_zone_str); 
    get_tzone_value(kwh_zone_str, bill->kwh_amount, 48);   
    bill->start_type = get_cmd_value(buf, "cmode");
}


uint32_t gtc_pal_time(void){
    return rtc_get_currt_time_sec();
}

//返回当前时间的小时数 0-23
uint32_t gtc_pal_get_int_hour(void){
    return rtc_get_currt_hour();
}

//返回当前时间的分钟数 0-59
uint32_t gtc_pal_get_int_minute(void){
    return rtc_get_currt_minute();
}

int8_t gtc_pal_write_persist_params(char* input,int size){
    return 0;
}
int8_t gtc_pal_read_persist_params(char* output,int limit){
    return 0;
}

int gtc_get_server_addr(char_t *addr, int32_t len){
    return data_getstr("rip", addr, len);
}

int gtc_get_server_port(void){
    return data_getint("rport");
}

int gtc_get_devid(char_t *id, int32_t len){
    return data_getstr("devid", id, len);
}

int32_t gtc_get_dev_type(void){
    int32_t mode = dev_get_dev_mode();
    if (mode == DEV_CHARGE_MODE_AC){
        return gtc_gun_type_ac;
    }else{
        return gtc_gun_type_dc;
    }
}

int pal_get_gun_cnt(void){
    return data_getint("gunnum");
}

int32_t pal_save_history_bill(char_t *order_id){
    record_save_to_history(order_id);
    return 0;
}

int32_t pal_save_current_bill(struct GtcBillInfo *record){
    char_t buf[500]={0};
    gtc_pack_record(record, buf);
    record_update(record->order_id, buf);
    return 0;
}

int8_t callback_save_bill(char* bill,uint32_t size){
    return 0;
}

int8_t callback_read_bill(struct GtcHistroyBill *bill, uint32_t cnt)
{
    #define name_len 50 
    #define name_cnt 4 
    assert(cnt <= name_cnt);
    char_t name_list[name_len*name_cnt]={0};
    int32_t num = record_read_charging_file_list(name_list, name_len, name_cnt);

    for(int32_t i=0;i<num;i++){
        printf("callback_read_bill name:%s\r\n", name_list + name_len*i);
        char_t buf[500]={0};
        if (record_read_charging_whth_dno(name_list + name_len*i, buf, sizeof(buf)) > 0){
            gtc_unpack_record(buf, &bill[i].bill);
            bill[i].status = gtc_bill_not_upload;
        }
    }
    return 0;
}
int32_t callback_card_ack(uint32_t gunnum, uint8_t ret){
	printf("card ack gunnum:%d %d\r\n", gunnum, ret);
    
    return 0;
}
void callback_start_charge(uint8_t gun_cnt,char* err)
{
    charger_start_charge(gun_cnt, err);
}

void callback_stop_charge(uint8_t gun_cnt, char* err){
    charger_stop_charge_by_server(gun_cnt);
}

int32_t callback_set_sys_time(uint32_t sec){
    return charger_sync_time((uint64_t)((uint64_t)sec*1000));
}

int32_t callback_set_net_state(uint8_t state){
    dev_set_net_state(state);
    return 0;
}

int32_t callback_reboot_system(void){
    log(LOG_INFO, "upgrade reboot sys\r\n");
    //event_log(0, EVENT_UPDATE_SUCCESS);
    os_msleep(3000);
    dev_reboot();
    return 0;
}

void calback_settle_set(uint8_t gun_id, uint32_t tcost){
    charger_settle_set(gun_id, tcost);
}

int32_t callback_get_update_info(uint8_t *buf, uint32_t len){
    return dta_get_update_info((char_t *)buf, len);
}

int32_t callback_save_update_file(uint8_t *buf, uint32_t len){
    return data_save_update_info_file((char_t *)buf, len);
}

int32_t callback_push_update_file_data(const char *name, int32_t pos, char_t *buf, int32_t len){
    return data_push_update_file_data(name, pos, buf, len);
}

